﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Epitech.Krisk.Xna.UI.Game.InGame.Gameplay;
using Epitech.Krisk.Xna.UI.Game.InGame.Gameplay.Objectifs;
using Microsoft.Xna.Framework;

namespace Epitech.Krisk.Xna.UI.Game.Utils
{
    public class ChargeAndSaveGame
    {
        /// <summary>
        /// Gets the list of games save files.
        /// </summary>
        public static List<String> GamesSave { get; protected set; }

        public static void ParseGames()
        {
            if (GamesSave == null)
            {
                GamesSave = new List<string>();

                if (!Directory.Exists("saves/"))
                    Directory.CreateDirectory("saves/");

                foreach (string s in Directory.GetFiles("saves/", "*.ks"))
                {
                    string tmp = s.Replace("saves/", "");
                    GamesSave.Add(tmp.Substring(0, tmp.Length - 3));
                }
            }
        }

        public static void Save(GamePlay game, String savename)
        {
            if (!Directory.Exists("saves"))
                Directory.CreateDirectory("saves");
            XDocument xmlfile = new XDocument();

            XElement hdr = new XElement("KRiskGame", new XAttribute("GameType", game.GameType.ToString()),new XAttribute("Name", savename));
            xmlfile.Add(hdr);
            XElement turn = new XElement("Turn", new XAttribute("State", game.GameTurn.State.ToString()), new XAttribute("Player", game.GameTurn.Player.Name));
            xmlfile.Element("KRiskGame").Add(turn);
            foreach (Player player in game.Players)
            {
                XElement playerElem = new XElement("Player", 
                    new XAttribute("Name", player.Name), new XAttribute("TimeToDeath", player.TimeToDeath.ToString()),
                    new XAttribute("State", player.State), new XAttribute("ReinforcementArmy", player.ReinforcementArmy),
                    new XAttribute("Color", player.Color.ToString()));

                if (game.GameType == GamePlayType.Classic)
                    playerElem.Add(new XElement("QuestCard", new XAttribute("ID", player.QuestCard.ID.ToString())));

                playerElem.Add(new XElement("Cards"));

                foreach (TerritoryCard card in player.Cards)
                {
                    XElement cardElem = new XElement("Card", new XAttribute("Type", card.CardType.ToString()));
                    playerElem.Element("Cards").Add(cardElem);
                }

                playerElem.Add(new XElement("Territories"));

                foreach (var territory in player.OwnTerritory)
                {
                    XElement territoryElem = new XElement("Territory", new XAttribute("Name", territory.Key.Name), new XAttribute("Continent", territory.Key.Continent.Name)
                        , new XAttribute("Army", territory.Value.TotalSoldier()));
                    playerElem.Element("Territories").Add(territoryElem);
                }

                xmlfile.Element("KRiskGame").Add(playerElem);
            }
            xmlfile.Save(String.Format("saves/{0}.ks", savename));

            if (GamesSave == null)
                GamesSave = new List<string>();

            if (!GamesSave.Contains(savename))
                GamesSave.Add(savename);
        }

        public static GamePlay Charge(String savename, GamePlay game)
        {
            if (GamesSave.Contains(savename))
            {
                XDocument save = XDocument.Load(String.Format("saves/{0}.ks", savename));

                GamePlayType gamePlayType;

                String gameType = save.Element("KRiskGame").Attribute("GameType").Value;
                var turn = save.Element("KRiskGame").Element("Turn");
                var players = save.Element("KRiskGame").Elements("Player");

                if (!GamePlayType.TryParse(gameType, out gamePlayType))
                {
                    return null;
                }

                game.GameType = gamePlayType;
                game.Players = new List<Player>();

                foreach (XElement player in players)
                {
                    Player pl = new Player();
                    pl.Name = player.Attribute("Name").Value;
                    pl.ReinforcementArmy = new Army(Convert.ToInt32(player.Attribute("ReinforcementArmy").Value));
                    pl.TimeToDeath = TimeSpan.Parse(player.Attribute("TimeToDeath").Value);
                    PlayerState playerState = pl.State;
                    Enum.TryParse(player.Attribute("State").Value, out playerState);
                    pl.State = playerState;
                    String color = player.Attribute("Color").Value;
                    int r = int.Parse(color.Split(' ')[0].Split(':')[1]);
                    int g = int.Parse(color.Split(' ')[1].Split(':')[1]);
                    int b = int.Parse(color.Split(' ')[2].Split(':')[1]);
                    int a = 255;
                    pl.Color = new Color(r, g, b, a);

                    var cards = player.Element("Cards").Elements();

                    foreach (XElement card in cards)
                    {
                        int idx = 0;
                        CardType type;
                        if (CardType.TryParse(card.Attribute("Type").Value, out type))
                        {
                            idx += game.Cards.TakeWhile(tc => type != tc.CardType).Count();
                            pl.Cards.Add(game.Cards[idx]);
                            game.Cards.RemoveAt(idx);
                        }
                    }

                    if (gamePlayType == GamePlayType.Classic)
                    {
                        int id = int.Parse(player.Element("QuestCard").Attribute("ID").Value);
                        foreach (var questCard in QuestCard.QuestCards)
                        {
                            if (questCard.ID == id)
                                pl.QuestCard = questCard;
                        }
                        QuestCard.QuestCards.Remove(pl.QuestCard);
                    }

                    var territories = player.Element("Territories").Elements();

                    pl.OwnTerritory = new Dictionary<Territory, Army>();

                    foreach (XElement territory in territories)
                    {
                        foreach (var territory1 in Territory.Territories)
                        {
                            if (territory1.Name == territory.Attribute("Name").Value)
                            {
                                int nb = int.Parse(territory.Attribute("Army").Value);
                                territory1.Owner = pl;
                                territory1.SpriteBatch = game.SpriteBatch;
                                territory1.Content = game.Content;
                                territory1.ViewPort = game.ViewPort;
                                pl.OwnTerritory.Add(territory1, new Army(nb));                                
                            }
                        }
                        Territory.Territories.Remove(pl.OwnTerritory.Last().Key);
                    }
                    game.Players.Add(pl);
                }

                TurnState state;
                if (TurnState.TryParse(turn.Attribute("State").Value, out state))
                {
                    game.GameTurn = new Turn {State = state};

                    foreach (var player in game.Players)
                    {
                        if (player.Name == turn.Attribute("Player").Value)
                            game.GameTurn.Player = player;
                    }

                }
            }
            return game;
        }
    }
}
